package javax.per.toolkit.tools;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Fun {
	
	private static String separator=", ";
	private static boolean showLineNumber=false;
	private static int lines=0;
	
	public static boolean isShowLineNumber() {
		return showLineNumber;
	}

	public static void setShowLineNumber(boolean showLineNumber) {
		Fun.showLineNumber = showLineNumber;
	}

	public static String getSeparator() {
		return separator;
	}

	public static void setSeparator(String separator) {
		Fun.separator = separator;
	}
	
	public static void pause(){
		Fun.getConsoleString();
	}

	public static void pl(Object obj){
		if(obj==null){
			System.out.println("null");
		}else if(obj.getClass().isArray()){
			String type=obj.getClass().getComponentType().getName();
			int index=type.lastIndexOf(".");
			if(index>0)
				type=type.substring(index+1);
			pl(type);
			if(type.equals("byte")){
				byte[] tmp=(byte[]) obj;
				for(byte b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Byte")){
				Byte[] tmp=(Byte[]) obj;
				for(Byte b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("int")){
				int[] tmp=(int[]) obj;
				for(int b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Integer")){
				Integer[] tmp=(Integer[]) obj;
				for(Integer b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("char")){
				char[] tmp=(char[]) obj;
				for(char b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Character")){
				Character[] tmp=(Character[]) obj;
				for(Character b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("short")){
				short[] tmp=(short[]) obj;
				for(short b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Short")){
				Short[] tmp=(Short[]) obj;
				for(Short b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("long")){
				long[] tmp=(long[]) obj;
				for(long b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Long")){
				Long[] tmp=(Long[]) obj;
				for(Long b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("float")){
				float[] tmp=(float[]) obj;
				for(float b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Float")){
				Float[] tmp=(Float[]) obj;
				for(Float b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("double")){
				double[] tmp=(double[]) obj;
				for(double b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("Double")){
				Double[] tmp=(Double[]) obj;
				for(Double b:tmp)
					pWithComma(b);
				pl("");
			}else if(type.equals("String")){
				String[] tmp=(String[]) obj;
				for(String b:tmp)
					pWithComma(b);
				pl("");
			}
		}else if(getInterfaces(obj).contains("java.lang.Iterable")){
			@SuppressWarnings("unchecked")
			Iterator<Object> it=((Iterable<Object>)obj).iterator();
			while(it.hasNext())
				pWithComma(it.next());
			pl("");
		}else{
			try{
				System.out.println(obj);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	public static void p(Object obj){
		if(obj==null){
			System.out.print("null");
		}else if(obj.getClass().isArray()){
			String type=obj.getClass().getComponentType().getName();
			int index=type.lastIndexOf(".");
			if(index>0)
				type=type.substring(index+1);
			pl(type);
			if(type.equals("byte")){
				byte[] tmp=(byte[]) obj;
				for(byte b:tmp)
					pWithComma(b);
			}else if(type.equals("Byte")){
				Byte[] tmp=(Byte[]) obj;
				for(Byte b:tmp)
					pWithComma(b);
			}else if(type.equals("int")){
				int[] tmp=(int[]) obj;
				for(int b:tmp)
					pWithComma(b);
			}else if(type.equals("Integer")){
				Integer[] tmp=(Integer[]) obj;
				for(Integer b:tmp)
					pWithComma(b);
			}else if(type.equals("char")){
				char[] tmp=(char[]) obj;
				for(char b:tmp)
					pWithComma(b);
			}else if(type.equals("Character")){
				Character[] tmp=(Character[]) obj;
				for(Character b:tmp)
					pWithComma(b);
			}else if(type.equals("short")){
				short[] tmp=(short[]) obj;
				for(short b:tmp)
					pWithComma(b);
			}else if(type.equals("Short")){
				Short[] tmp=(Short[]) obj;
				for(Short b:tmp)
					pWithComma(b);
			}else if(type.equals("long")){
				long[] tmp=(long[]) obj;
				for(long b:tmp)
					pWithComma(b);
			}else if(type.equals("Long")){
				Long[] tmp=(Long[]) obj;
				for(Long b:tmp)
					pWithComma(b);
			}else if(type.equals("float")){
				float[] tmp=(float[]) obj;
				for(float b:tmp)
					pWithComma(b);
			}else if(type.equals("Float")){
				Float[] tmp=(Float[]) obj;
				for(Float b:tmp)
					pWithComma(b);
			}else if(type.equals("double")){
				double[] tmp=(double[]) obj;
				for(double b:tmp)
					pWithComma(b);
			}else if(type.equals("Double")){
				Double[] tmp=(Double[]) obj;
				for(Double b:tmp)
					pWithComma(b);
			}else if(type.equals("String")){
				String[] tmp=(String[]) obj;
				for(String b:tmp)
					pWithComma(b);
			}
		}else if(getInterfaces(obj).contains("java.lang.Iterable")){
			@SuppressWarnings("unchecked")
			Iterator<Object> it=((Iterable<Object>)obj).iterator();
			while(it.hasNext())
				pWithComma(it.next());
		}else{
			try{
				System.out.print(obj);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	public static Set<String> getInterfaces(Object obj){
		Set<String> set=new HashSet<String>();
		getInterfacesLoop(set,obj.getClass());
		return set;
	}
	
	@SuppressWarnings("rawtypes")
	private static void getInterfacesLoop(Set<String> set,Class obj){
		Class[] cla=obj.getInterfaces();
		for(Class c:cla){
			set.add(c.getName());
			getInterfacesLoop(set,c);
		}
		Class cla1=obj.getSuperclass();
		if(cla1!=null&&!cla1.equals(Object.class)){
			getInterfacesLoop(set,cla1);
		}
	}
	
	private static void pWithComma(Object obj){
		if(showLineNumber){
			System.out.print(""+lines+++"  "+obj+separator);
		}else
			System.out.print(obj+separator);
	}
	
	
	public static String type(Object obj){
		if(obj.getClass().isArray()){
			return obj.getClass().getComponentType().getName();
		}else{
			return obj.getClass().getSimpleName();
		}
	}
	
	public static String getInvoker(){
		StackTraceElement[] eles=Thread.currentThread().getStackTrace();
		boolean find=false;
		for(StackTraceElement ele:eles){
			if(find==true){
				return ele.getMethodName();
			}
			if(ele.getMethodName().equals("getInvoker")){
				find=true;
			}
		}
		return "";
	}
	
	public static Class<?> getInvokerClass() throws ClassNotFoundException{
		StackTraceElement[] eles=Thread.currentThread().getStackTrace();
		boolean find=false;
		for(StackTraceElement ele:eles){
			if(find==true){
				return Class.forName(ele.getClassName());
			}
			if(ele.getMethodName().equals("getInvokerClass")){
				find=true;
			}
		}
		return null;
	}
	
	public static Class<?> getInvokerSuperClass() throws ClassNotFoundException{
		StackTraceElement[] eles=Thread.currentThread().getStackTrace();
		boolean find=false;
		boolean add=false;
		for(StackTraceElement ele:eles){
			if(find==true&&add==false){
				add=true;
				continue;
			}
			if(find==true&&add==true){
				return Class.forName(ele.getClassName());
			}
			if(ele.getMethodName().equals("getInvokerSuperClass")){
				find=true;
			}
		}
		return null;
	}
	
	public static void printStackTrace(){
		StackTraceElement[] eles=Thread.currentThread().getStackTrace();
		for(StackTraceElement ele:eles){
			pl("class name:"+ele.getClassName()+"\tfield name:"+ele.getFileName()+"\tmethod name:"+ele.getMethodName()+"\tline number:"+ele.getLineNumber());
		}
	}

	public static List<File> getSubFiles(String dir){
		List<File> fileList=new ArrayList<File>();
		findFileLoop(fileList,new File(dir));
		return fileList;
	}
	
	private static void findFileLoop(List<File> fileList,File file){
		if(file.isDirectory()){
			fileList.add(file);
			for(File f:file.listFiles()){
				findFileLoop(fileList,f);
			}
		}else{
			fileList.add(file);
		}
	}

	public static List<File> getSubFiles(String dir,String[] reg){
		List<File> fileList=new ArrayList<File>();
		findFileLoop(fileList,new File(dir),reg);
		return fileList;
	}
	
	private static void findFileLoop(List<File> fileList,File file,String[] reg){
		if(file.isDirectory()){
			for(File f:file.listFiles()){
				findFileLoop(fileList,f,reg);
			}
		}else{
			for(String r:reg){
				Pattern pa=Pattern.compile(r.toLowerCase());
				Matcher ma=pa.matcher(file.getName().toLowerCase());
				if(ma.matches()){
					fileList.add(file);
					break;
				}
			}
		}
	}
	
	public static String getConsoleString(){
		Scanner san=new Scanner(System.in);
		String str=san.nextLine();
		//san.close(); it will close system in
		return str;
	}
	
	public static int getConsoleInt(){
		Scanner san=new Scanner(System.in);
		boolean get=false;
		int str = 0;
		while(!get){
			try{
				while(!san.hasNext()){
					Thread.sleep(10);
				}
			str=san.nextInt();
			get=true;
			}catch(Exception e){
				Log.getLogger().debug("Format Error");
				get=false;
				san.next();
			}
		}
		//san.close();
		return str;
	}
	
	public static String escapeStrForRep(String str){
		return str.replaceAll("\\\\", "\\\\\\\\").replaceAll("\\.", "\\\\.").replaceAll("\\*", "\\\\*").replaceAll("\\(", "\\\\(")
		.replaceAll("\\)", "\\\\)").replaceAll("\\[", "\\\\[").replaceAll("\\]", "\\\\]").replaceAll("\\?", "\\\\?").replaceAll("\\+", "\\\\+")
		.replaceAll("\\+", "\\\\+").replaceAll("\\:", "\\\\:").replaceAll("\\!", "\\\\!").replaceAll("\\{", "\\\\{")
		.replaceAll("\\}", "\\\\}");
	}
	
}

